package process

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"
	"retalk/client/utils"
	"retalk/common/entity"
	"retalk/common/message"
)

type UserProcess struct {
}

//客户端用户登录
func (this *UserProcess) Login(userid int, userpwd string) (err error) {
	//登录信息验证
	//1. 连接到服务器
	conn, err := net.Dial("tcp", "127.0.0.1:8889")
	if err != nil {
		fmt.Println("net.Dial err=", err)
		return
	}
	defer conn.Close()

	//2. 准备通过 conn 发送消息给服务器
	var mes message.Message
	mes.Type = message.LoginMesType
	//3. 创建一个消息
	var loginMes message.LoginMes
	loginMes.UserId = userid
	loginMes.UserPwd = userpwd

	//4. 将loginMes序列化
	data, err := json.Marshal(loginMes)
	if err != nil {
		fmt.Println("json Marshal err=", err)
		return
	}

	//5. 把data赋给mes.Data字段
	mes.Data = string(data)

	//6. 将 mes 进行序列化
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("json Marshal err=", err)
		return
	}

	//7. 发送data内容
	//7.1 先发送data的长度:获取data的长度，转成一个表示长度的byte切片
	var pkgLen uint32
	pkgLen = uint32(len(data))
	var buf [4]byte
	binary.BigEndian.PutUint32(buf[0:4], pkgLen)
	//发送长度
	n, err := conn.Write(buf[0:4])
	if n != 4 || err != nil {
		fmt.Println("客户端用户登录 登录消息长度发送失败　err=", err)
		return
	}
	fmt.Printf("客户端用户登录 发送 消息长度为 %v \n", len(data))
	//发送消息自身
	_, err = conn.Write(data)
	if err != nil {
		fmt.Println("客户端用户登录 消息内容发送失败　err=", err)
		return
	}
	fmt.Printf("客户端用户登录 发送 消息内容为 %v\n", string(data))

	transfer := utils.Transfer{
		Conn: conn,
	}
	mes, err = transfer.ReadPkg()
	if err != nil {
		fmt.Println("登录返回消息内容读取失败　err=", err)
		return
	}
	//将mes中Data部分反序列化成LoginResMes
	var loginResMes message.LoginResMes
	err = json.Unmarshal([]byte(mes.Data), &loginResMes)
	if loginResMes.Code == 200 { //登录成功
		//初始化CurUser
		CurUser.Conn = conn
		CurUser.UserId = userid
		CurUser.UserStatus = message.UserOnline

		//显示在线用户列表
		fmt.Println("当前在线用户列表：")
		for _, v := range loginResMes.UserIds {
			if v == userid { //不显示自己
				continue
			}
			fmt.Printf("用户:%v\n", v)
			//完成客户端onLineUsers的初始化
			user := &entity.User{
				UserId:     v,
				UserStatus: message.UserOnline,
			}
			onLineUsers[v] = user
		}
		fmt.Println()
		//1. 启动协程和服务器端保持通讯，如果服务器有信息则显示
		go ServerProcessMes(conn)

		//循环显示菜单
		for {
			ShowMenu()
		}
	} else {
		fmt.Println("登录失败:", loginResMes.Error)
	}
	return
}

//客户端用户注册
func (this *UserProcess) Register(userid int, userpwd, username string) (err error) {
	conn, err := net.Dial("tcp", "127.0.0.1:8889")
	if err != nil {
		fmt.Println("net.Dial err=", err)
		return
	}
	defer conn.Close()

	//2. 准备通过 conn 发送消息给服务器
	var mes message.Message
	mes.Type = message.RegisterMesType
	//3. 创建一个消息
	var registerMes message.RegisterMes
	registerMes.User.UserId = userid
	registerMes.User.UserPwd = userpwd
	registerMes.User.UserName = username

	//4. 将registerMes序列化
	data, err := json.Marshal(registerMes)
	if err != nil {
		fmt.Println("json Marshal err=", err)
		return
	}

	//5. 把data赋给mes.Data字段
	mes.Data = string(data)

	//6. 将 mes 进行序列化
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("json Marshal err=", err)
		return
	}

	//7. 发送data内容
	transfer := utils.Transfer{
		Conn: conn,
	}
	err = transfer.WritePkg(data)
	if err != nil {
		fmt.Println("注册消息内容发送失败　err=", err)
		return
	}

	mes, err = transfer.ReadPkg()
	if err != nil {
		fmt.Println("注册返回消息内容读取失败　err=", err)
		return
	}

	//将mes中Data部分反序列化成RegisterMes
	var registerResMes message.RegisterResMes
	err = json.Unmarshal([]byte(mes.Data), &registerResMes)
	if registerResMes.Code == 200 { //注册成功
		fmt.Println("注册成功，请重新登录...")
		return
	} else {
		fmt.Println("注册失败:", registerResMes.Error)
		return
	}
}
